package com.whfc.safety.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whfc.base.param.AppFileExportParam;
import com.whfc.base.service.AppExportService;
import com.whfc.common.enums.DelFlag;
import com.whfc.common.exception.BizException;
import com.whfc.common.file.FileHandler;
import com.whfc.common.file.FilePathConfig;
import com.whfc.common.file.properties.FileExpirationRules;
import com.whfc.common.result.PageData;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.util.*;
import com.whfc.safety.dao.SafetyFineImgMapper;
import com.whfc.safety.dao.SafetyFineMapper;
import com.whfc.safety.dao.SafetyFineUserMapper;
import com.whfc.safety.dto.SafetyFineDTO;
import com.whfc.safety.dto.SafetyFineNumDTO;
import com.whfc.safety.entity.SafetyFine;
import com.whfc.safety.entity.SafetyFineUser;
import com.whfc.safety.param.SafetyFineAddParam;
import com.whfc.safety.param.SafetyFineCompleteParam;
import com.whfc.safety.service.SafetyFineService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.io.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author hw
 * @description 质量罚款单
 * @date 2021/8/13
 */
@DubboService(interfaceClass = SafetyFineService.class, version = "1.0.0")
public class SafetyFineServiceImpl implements SafetyFineService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private SafetyFineMapper qualityFineMapper;

    @Autowired
    private SafetyFineImgMapper qualityFineImgMapper;

    @Autowired
    private SafetyFineUserMapper safetyFineUserMapper;

    @DubboReference(interfaceClass = AppExportService.class, version = "1.0.0")
    private AppExportService appExportService;

    @Autowired
    private FilePathConfig msFilePathConfig;

    @Autowired
    private FileHandler fileHandler;

    private final static String EXPORT_IMG_TEMPLATE = "<img src='%s' />";

    private final static String QUALITY_FILE_DESC = "安全违章罚款通知单导出";

    private final static String HTML_TEMPLATE_PATH = "pdfTemp/safetyFineTemp.html";

    private JSONObject pdfConfig;

    private final static String PDF_CONFIG_PATH = "pdfConfig/config.json";

    @PostConstruct
    public void info() throws IOException {
        ClassPathResource resource = new ClassPathResource(PDF_CONFIG_PATH);
        InputStream templateFileInputStream = resource.getInputStream();
        String pdfConfigStr = new String(FileUtil.readData(templateFileInputStream));
        if (StringUtils.isNotEmpty(pdfConfigStr)) {
            pdfConfig = JSONObject.parseObject(pdfConfigStr);
        }
    }

    @Override
    public void add(SafetyFineAddParam param) throws BizException {
        logger.info("添加质量罚款单,param:{}", param);
        SafetyFine qualityFine = new SafetyFine();
        BeanUtils.copyProperties(param, qualityFine);
        qualityFineMapper.insertSelective(qualityFine);
        SafetyFineUser fineUser = new SafetyFineUser();
        fineUser.setFineId(qualityFine.getId());
        fineUser.setUserId(qualityFine.getUserId());
        fineUser.setUserName(qualityFine.getUserName());
        fineUser.setTime(new Date());
        fineUser.setType(1);
        safetyFineUserMapper.insertSelective(fineUser);
        List<String> urls = param.getImgUrls();
        if (urls != null && !urls.isEmpty()) {
            qualityFineImgMapper.insertAll(qualityFine.getId(), urls);
        }
    }

    @Override
    public SafetyFineNumDTO num(Integer deptId, String corpName, String userName, Date startTime, Date endTime) throws BizException {
        logger.info("质量罚款统计,deptId：{},corpName：{},userName：{},startTime：{},endTime：{}",
                deptId, corpName, userName, startTime, endTime);
        return qualityFineMapper.selectNumByDeptId(deptId, corpName, userName, startTime, endTime);
    }

    @Override
    public PageData<SafetyFineDTO> list(Integer deptId, String corpName, String userName, String state, Date startTime, Date endTime, Integer pageSize, Integer pageNum) throws BizException {
        logger.info("质量罚单列表,deptId：{},corpName：{},userName：{},state：{},startTime：{},endTime：{},pageNum：{},pageSize：{}",
                deptId, corpName, userName, state, startTime, endTime, pageNum, pageSize);
        if (endTime != null) {
            endTime = DateUtil.getDateEnd(endTime);
        }
        List<Integer> states = null;
        if (StringUtils.isNotEmpty(state)) {
            states = Arrays.stream(state.split(",")).map(Integer::valueOf).collect(Collectors.toList());
        }
        PageHelper.startPage(pageNum, pageSize);
        List<SafetyFineDTO> list = qualityFineMapper.selectByDeptId(deptId, corpName, userName, states, startTime, endTime);
        for (SafetyFineDTO qualityFineDTO : list) {
            List<String> url = qualityFineImgMapper.selectByFineId(qualityFineDTO.getFineId());
            qualityFineDTO.setImgUrls(url);
        }
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public void del(Integer fineId) throws BizException {
        logger.info("删除质量罚单,fineId:{}", fineId);
        SafetyFine qualityFine = qualityFineMapper.selectByPrimaryKey(fineId);
        if (qualityFine == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "删除数据不存在");
        }
        qualityFine.setDeptId(DelFlag.DELETE.getValue());
        qualityFineMapper.updateByPrimaryKeySelective(qualityFine);
    }

    @Override
    public void complete(SafetyFineCompleteParam param) throws BizException {
        logger.info("处理质量罚款单,param:{}", param);
        SafetyFine qualityFine = new SafetyFine();
        BeanUtils.copyProperties(param, qualityFine);
        qualityFine.setId(param.getFineId());
        SafetyFineUser fineUser = new SafetyFineUser();
        fineUser.setFineId(param.getFineId());
        fineUser.setUserId(param.getUserId());
        fineUser.setUserName(param.getUserName());
        fineUser.setTime(new Date());
        if (param.getState().equals(0)) {
            fineUser.setType(1);
        } else if (param.getState().equals(10) || param.getState().equals(11)) {
            fineUser.setType(2);
        } else if (param.getState().equals(20) || param.getState().equals(21)) {
            fineUser.setType(3);
        }

        safetyFineUserMapper.insertSelective(fineUser);
        qualityFineMapper.updateByPrimaryKeySelective(qualityFine);
    }

    @Override
    public void fineExport(List<Integer> fineIds, Integer deptId) throws BizException {
        String fileDesc = QUALITY_FILE_DESC;
        String fileName = RandomUtil.getRandomFileName();
        String suffix = fineIds.size() > 1 ? "zip" : "pdf";
        AppFileExportParam fileExport = new AppFileExportParam();
        fileExport.setDeptId(deptId);
        fileExport.setFileName(fileName);
        fileExport.setFileFormat(suffix.toUpperCase());
        fileExport.setFileState(0);
        fileExport.setFileDesc(fileDesc);
        Integer id = appExportService.install(fileExport);
        fileExport.setId(id);
        AppFileExportParam upFileExport = fileExport;
        CompletableFuture.supplyAsync(() -> {
            List<InputStream> iss = new ArrayList<>();
            String footer = null;
            String header = null;
            if (pdfConfig.containsKey(deptId.toString())) {
                JSONObject config = pdfConfig.getJSONObject(deptId.toString());
                footer = config.getString("footer");
                header = config.getString("header");
            }
            for (Integer fineId : fineIds) {
                SafetyFine qualityFine = qualityFineMapper.selectByPrimaryKey(fineId);
                JSONObject data = new JSONObject();
                data.put("corpName", qualityFine.getCorpName());
                data.put("money", qualityFine.getMoney() + "元");
                data.put("time", DateUtil.formatDate(qualityFine.getTime(), DateUtil.DATE_TIME_FORMAT));
                data.put("remark", qualityFine.getRemark());
                data.put("handleOpinion", qualityFine.getHandleOpinion());

                List<SafetyFineUser> users = safetyFineUserMapper.selectByFineId(fineId);
                if (!users.isEmpty()) {
                    users.forEach(qualityFineUser -> {
                        if (qualityFineUser.getType().equals(1)) {
                            data.put("userName", qualityFineUser.getUserName());
                            data.put("userTime", DateUtil.formatDate(qualityFineUser.getTime(), DateUtil.DATE_TIME_FORMAT));
                        } else if (qualityFineUser.getType().equals(2)) {
                            data.put("handleUserName1", qualityFineUser.getUserName());
                            data.put("handleUserTime1", DateUtil.formatDate(qualityFineUser.getTime(), DateUtil.DATE_TIME_FORMAT));
                        } else if (qualityFineUser.getType().equals(3)) {
                            data.put("handleUserName2", qualityFineUser.getUserName());
                            data.put("handleUserTime2", DateUtil.formatDate(qualityFineUser.getTime(), DateUtil.DATE_TIME_FORMAT));
                        }
                    });
                }
                ClassPathResource resource = new ClassPathResource(HTML_TEMPLATE_PATH);
                String html;
                try {
                    InputStream templateFileInputStream = resource.getInputStream();
                    File tempFile = FileUtil.copyTemplateFile(templateFileInputStream);
                    html = HtmlUtil.freeMarkerRender(data, tempFile);
                    ByteArrayOutputStream arrayOutputStream = ItextPdfUtil.htmlToPdf(html, header, footer);
                    iss.add(new ByteArrayInputStream(arrayOutputStream.toByteArray()));
                } catch (IOException e) {
                    logger.error("质量罚款单pdf导出异常", e);
                }
            }
            InputStream is = null;
            if (suffix.equals("zip")) {
                try {
                    is = ZipUtil.zipPdfFile(iss);
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error("压缩文件失败", e);
                }
            } else {
                is = iss.get(0);
            }
            String path = msFilePathConfig.getFilePath("quality/export", fileName, suffix);
            String upload = fileHandler.upload(path, is, FileExpirationRules.DAYS_7);
            upFileExport.setFileUrl(upload);
            upFileExport.setFileState(1);
            appExportService.update(upFileExport);
            return null;
        });
    }

    @Override
    public void deleteBatch(List<Integer> idList) {
        if(CollectionUtils.isEmpty(idList)){
            return;
        }
        qualityFineMapper.deleteBatch(idList);
    }

}
